
#pragma comment ( lib, "shlwapi.lib" )
#include <shlwapi.h>
#include <algorithm>
#include "path.h"

using namespace fs;

std::string path_append( const std::string & path, const std::string & more )
{
	char buf[MAX_PATH];
	strcpy_s( buf, MAX_PATH, path.c_str() );
	::PathAppendA( buf, more.c_str() );
	return buf;
}

std::string path_add_backslash( const std::string & path )
{
	char buf[MAX_PATH];
	strcpy_s( buf, MAX_PATH, path.c_str() );
	::PathAddBackslashA( buf );
	return buf;
}

////////////////////////////////////////////////
////////////////////////////////////////////////

Path::Path()
{
	*this = current_directory();
}

Path::Path( const std::string &path )
{
	_path = path;
	canonicalize();
}

Path::Path(const fs::Path &other)
{
	_path = other._path;
}

Path & Path::operator=( const Path & other )
{
	Path tmp( other );
	swap( tmp );
	return *this;
}

void Path::swap( Path other )
{
	std::swap( _path, other._path );
}

bool Path::is_directory() const
{
	return ::PathIsDirectoryA( _path.c_str() )? true:false;
}

bool Path::is_exist() const
{
	return ::PathFileExistsA( _path.c_str() )? true : false;
}


std::string Path::extension() const
{
	char* q = ::PathFindExtensionA( _path.c_str() );
	return *q ? q + 1: q ;

}

Path Path::current_directory()
{
	char buf[MAX_PATH];
	::GetCurrentDirectoryA( MAX_PATH, buf );
	return Path( buf );
}

Path& Path::canonicalize()
{
	std::replace( _path.begin(), _path.end(), '/', '\\' );
	char buf[MAX_PATH];
	::PathCanonicalizeA( buf, _path.c_str() );
	::PathRemoveBackslashA( buf );
	_path.assign( buf );
	return *this;
}

Path & Path::operator+=( const Path & other )
{
	_path = path_append( _path, other._path );
	return *this;
}

bool Path::operator==( const Path & other )
{
	return _path == other._path;
}

bool Path::operator!=( const Path & other )
{
	return ! operator==( other );
}

Path fs::operator+( const Path & path1, const Path & path2 )
{
	Path tmp( path1 );
	tmp += path2;
	return tmp;
}

std::string Path::as_string( bool trailing_backslash_flag ) const
{
	if( trailing_backslash_flag )
	{
		return path_add_backslash( _path );
	}
	else
	{
		return _path;
	}
}

std::ostream & fs::operator<<( std::ostream & os, const Path & path )
{
	return os << path._path;
}

std::istream & fs::operator>>( std::istream & is, Path & path )
{
	std::string s;
	is >> s;
	path = Path( s );
	return is;
}

Path::operator std::string()
{
	return as_string();
}
